package context

import (
	"encoding/json"
	"strconv"

	"yingsheng.com/go-api-server/constant"
	"yingsheng.com/go-api-server/errors"
)

type Session struct {
	Context *Context
	// 登录会话用户信息
	UserInfo UserInfo
	// 登录会话其他信息
	OtherInfo OtherInfo
	// 登录用户所在企业信息
	CorpInfo CorpInfo

	ssoData       SsoDataInfo
	corpData      CorpDataInfo
	corpDataAdmin CorpDataAdminInfo
}

// 创建新的会话对象
func NewSession() *Session {
	return &Session{}
}

// 重置会话对象
func (s *Session) Reset(ctx *Context) {
	s.Context = ctx
	s.ssoData = SsoDataInfo{}
	s.corpData = CorpDataInfo{}
	s.corpDataAdmin = CorpDataAdminInfo{}
}

// 从微服务加载企业管理员状态
func (s *Session) loadCorpAdmin(companyID string) {
	var (
		err      error
		jsonByte []byte
	)

	reqInfo := s.Context.NewRequestInfo("corp.admin.verify")
	reqInfo["userID"] = strconv.FormatInt(s.UserInfo.UserID, 10)
	reqInfo["companyID"] = companyID

	jsonByte, err = s.Context.Module.Get(reqInfo)
	if err == nil {
		err = json.Unmarshal(jsonByte, &s.corpDataAdmin)
	}

	if err != nil {
		err = errors.NewSys(err)
	}

	s.corpDataAdmin.Err = err
}

// 从微服务加载用户企业信息
func (s *Session) loadCorp(companyID string) {
	if s.corpData.IsLoad {
		return
	}

	var (
		err      error
		jsonByte []byte
	)

	reqInfo := s.Context.NewRequestInfo("corp.member.get")
	reqInfo["userID"] = strconv.FormatInt(s.UserInfo.UserID, 10)
	reqInfo["companyID"] = companyID

	jsonByte, err = s.Context.Module.Get(reqInfo)
	if err == nil {
		err = json.Unmarshal(jsonByte, &s.corpData)
	}

	if err != nil {
		err = errors.NewSys(err)
	} else {
		s.CorpInfo = s.corpData.Data.Member
	}

	s.corpData.IsLoad = true
	s.corpData.Err = err
}

// 从微服务加载会话信息
func (s *Session) loadSso() {
	if s.ssoData.IsLoad {
		return
	}

	var (
		err      error
		jsonByte []byte
	)

	reqInfo := s.Context.NewRequestInfo("user.session.info")

	jsonByte, err = s.Context.Module.Get(reqInfo)
	if err == nil {
		err = json.Unmarshal(jsonByte, &s.ssoData)
	}

	if err != nil {
		err = errors.NewSys(err)
	} else {
		s.UserInfo = s.ssoData.Data.User
		s.OtherInfo = s.ssoData.Data.Other
	}

	s.ssoData.IsLoad = true
	s.ssoData.Err = err
}

// 用户是否登录状态
func (s *Session) IsLogin() bool {
	isLogin, _ := s.CheckLogin()
	return isLogin
}

// 检查用户是否登录
func (s *Session) CheckLogin() (isLogin bool, err error) {
	s.loadSso()

	if s.ssoData.Err == nil {
		isLogin = s.ssoData.Code == constant.RESPONSE_CODE_OK
	} else {
		err = s.ssoData.Err
	}

	return
}

// 获取用户会话信息接口的请求状态
func (s *Session) GetLoginStatus() (code int, msg string) {
	code, msg = s.ssoData.Code, s.ssoData.Msg
	return
}

// 用户是否该企业成员
func (s *Session) IsCorpMember(companyID string) bool {
	isMember, _ := s.CheckCorpMember(companyID)

	return isMember
}

// 检查用户是否该企业成员
func (s *Session) CheckCorpMember(companyID string) (isMember bool, err error) {
	isMember, err = s.CheckLogin()
	if err != nil || !isMember {
		s.corpData.Code = s.ssoData.Code
		s.corpData.Msg = s.ssoData.Msg
		return
	}
	isMember = false

	s.loadCorp(companyID)

	if s.corpData.Err == nil {
		isMember = s.corpData.Code == constant.RESPONSE_CODE_OK

		if !isMember && s.corpData.Code == 10204 {
			// 用户不存在于任何企业，定义错误代码
			s.corpData.Code = constant.RESPONSE_CODE_CORP_ACCOUNT_INVALID
		}
	} else {
		err = s.corpData.Err
	}

	return
}

// 获取用户企业成员信息接口的请求状态
func (s *Session) GetCorpMemberStatus() (code int, msg string) {
	code, msg = s.corpData.Code, s.corpData.Msg
	return
}

// 用户是否该企业超级管理员
func (s *Session) IsCorpAdmin(companyID string) bool {
	isAdmin, _ := s.CheckCorpAdmin(companyID)

	return isAdmin
}

// 检查用户是否企业超级管理员
func (s *Session) CheckCorpAdmin(companyID string) (isAdmin bool, err error) {
	isAdmin, err = s.CheckLogin()
	if err != nil || !isAdmin {
		s.corpDataAdmin.Code = s.ssoData.Code
		s.corpDataAdmin.Msg = s.ssoData.Msg
		return
	}
	isAdmin = false

	s.loadCorpAdmin(companyID)

	if s.corpDataAdmin.Err == nil {
		if s.corpDataAdmin.Code == constant.RESPONSE_CODE_OK {
			isAdmin = s.corpDataAdmin.Data.Result

			if !isAdmin {
				// 用户不是企业超级管理员，定义错误代码
				s.corpDataAdmin.Code = constant.RESPONSE_CODE_CORP_ADMIN_INVALID
			}
		}
	} else {
		err = s.corpDataAdmin.Err
	}

	return
}

// 获取用户企业成员信息接口的请求状态w	e
func (s *Session) GetCorpAdminStatus() (code int, msg string) {
	code, msg = s.corpDataAdmin.Code, s.corpDataAdmin.Msg
	return
}
